home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / STANDALO / COMMENTF / COMMENT.C < prev   
Text File  |  1990-04-22  |  14KB  |  557 lines

  1.  
  2. /*----------------------------------------------------------------------------+
  3. |                                                                             |
  4. |    comment.c                                                                 |
  5. |                                                                             |
  6. |    This is code for an FKEY to do various commenting functions for C code.   |
  7. |    It takes text on the clipboard (or on the TEScrap), operates on it,       |
  8. |    and replaces it.                                                          |
  9. |                                                                              |
  10. |    If the option key is pressed within KEYDELAY ticks after the FKEY is      |
  11. |    called, the clipboard text will be commented with a line running down     |
  12. |    the left side, and the text indented with tabs.                           |
  13. |                                                                              |
  14. |    If the tab key is pressed within KEYDELAY ticks, the text will be         |
  15. |    surrounded with / * and * / characters, and any previously commented      |
  16. |    text will be replaced with SLASHREPLACEMENT (since commented comments     |
  17. |    aren't allowed in C).                                                     |
  18. |                                                                              |
  19. |    If the accent ("`") key is pressed with KEYDELAY ticks, the text          |
  20. |    will be assumed to have been previously commented, and any surrounding    |
  21. |    comment marks will be removed and any temporarily uncommented lines       |
  22. |    will be commented back in.  It is the inverse of the previous             |
  23. |    operation.                                                                |
  24. |                                                                              |
  25. |    If no key is pressed within KEYDELAY ticks, the text will be surrounded   |
  26. |    in a large box, like this one.                                            |
  27. |                                                                              |
  28. |    This FKEY does not (yet) work with programs that keep a private           |
  29. |    scrap (such as Word).  How can I easily trick those programs into         |
  30. |    putting their scrap on the clipboard?                                     |
  31. |                                                                              |
  32. |    This code and FKEY is free, but may not be resold and is copyrighted      |
  33. |    1990 by David S. Fry.                                                     |
  34. |                                                                              |
  35. |    David Fry                                                                 |
  36. |    81 Irving Street                                                          |
  37. |    Cambridge, MA 02138                                                       |
  38. |    INTERNET: fry@math.harvard.edu                                            |
  39. |    April 22, 1990                                                            |
  40. |                                                                              |
  41. +----------------------------------------------------------------------------*/
  42.  
  43. /* my own version of isspace() */
  44. #define        isspace(x)        (( (x) <= ' ' ) ? TRUE : FALSE)
  45.  
  46. #define        TABSPACE            4        /* spaces for tab in editor */
  47. #define        LEFTCHAR            '|'        /* left char on box            */
  48. #define        RIGHTCHAR            '|'        /* right char on box        */
  49. #define        LINELEN                78        /* length of line            */
  50. #define        TOPCHAR                '-'        /* top of box                */
  51. #define        BOTCHAR                '-'        /* bottom of box            */
  52. #define        CORNERCHAR            '+'        /* corner of box            */
  53. #define        SIDECHAR            '*'        /* left side char            */
  54. #define        SLASHREPLACEMENT    '|'        /* what to replace "/" with */
  55.  
  56. #define        NULL                0L
  57.  
  58. /* how many ticks to wait for user to press option, tab, or accent */
  59. #define        KEYDELAY        45
  60.  
  61. /* key codes */
  62. #define        option_kc        58
  63. #define        tab_kc            48
  64. #define        accent_kc        50
  65.  
  66. /*----------------------------------------------------------------------------+
  67. |            Add text from little buffer to the big output buffer.             |
  68. +----------------------------------------------------------------------------*/
  69.                 
  70. Ptr    AddToOutText(textBuf,addBuf,len)
  71. Ptr        textBuf,addBuf;
  72. long    len;
  73. /*
  74. *    This function takes text from the temporary buffer addBuff and
  75. *    adds it to the text buffer textBuf.
  76. *    
  77. *    If there's a problem, it kills textBuf and returns NULL.
  78. */
  79. {
  80.     long        outSize;
  81.     Ptr            temp;
  82.     
  83.     outSize = GetPtrSize(textBuf);
  84.     SetPtrSize(textBuf,outSize+len);
  85.     if ( MemError() != noErr ) {
  86.         /* hit a nonreloc block */
  87.         temp = NewPtr((long)(outSize+len));
  88.         if ( temp == NULL ) {
  89.             DisposPtr(textBuf);
  90.             return(NULL);
  91.         }
  92.         BlockMove(textBuf,temp,outSize);
  93.         DisposPtr(textBuf);
  94.         textBuf = temp;
  95.     }
  96.     
  97.     BlockMove(addBuf,textBuf+outSize,len);
  98.     return(textBuf);
  99. }
  100.  
  101. /*----------------------------------------------------------------------------+
  102. |                    Check for key presses.                                    |
  103. +----------------------------------------------------------------------------*/
  104.                     
  105. Boolean  CheckKeyCode(kc)
  106. char        kc;
  107. /*
  108. *    Checks to see if the key with kc key code is down
  109. */
  110. {
  111.     KeyMap        theKeys;
  112.     
  113.     GetKeys(&theKeys);
  114.     return( BitTst(&theKeys, 
  115.         (long) ((kc/8)*8 + 7 - (kc%8) ) ));
  116. }
  117.  
  118. /*----------------------------------------------------------------------------+
  119. |                    Comment out (and in) large sections.                      |
  120. |                   Called if the tab key or "`" key is pressed.              |
  121. +----------------------------------------------------------------------------*/
  122.  
  123. Ptr    CommentOut(inH,inSize,addcmts)
  124. Handle    inH;
  125. long    inSize;
  126. Boolean    addcmts;
  127. /*
  128. *    returns pointer to text
  129. */
  130. {
  131.     long        y;
  132.     char        *inT, *endT;
  133.     char        *outT;
  134.     char        buf[10];
  135.     long        beginning, ending;
  136.     char        *temp;
  137.     
  138.     inT = *inH;
  139.     endT = inT + inSize;
  140.     outT = NewPtr(0L);
  141.     
  142.     if ( addcmts ) {
  143.     
  144.         /*
  145.         *    We will comment out the whole section, and replace
  146.         *    any existing comments.
  147.         */
  148.         
  149.         y = 0;
  150.         buf[y++] = '/';
  151.         buf[y++] = '*';
  152.         buf[y++] = '\r';
  153.         outT = AddToOutText(outT,buf,y);
  154.         if ( outT == NULL )
  155.             return(NULL);
  156.         
  157.         while ( inT < endT ) {
  158.             if ( *inT == '/' && 
  159.                 (*(inT + 1) == '*' || *(inT-1) == '*') )
  160.                 *inT = SLASHREPLACEMENT;
  161.             inT++;
  162.         }
  163.         inT = *inH;
  164.         outT = AddToOutText(outT,inT,inSize);
  165.         if ( outT == NULL )
  166.             return(NULL);
  167.             
  168.         y = 0;
  169.         buf[y++] = '*';
  170.         buf[y++] = '/';
  171.         buf[y++] = '\r';
  172.         outT = AddToOutText(outT,buf,y);
  173.         
  174.     } else {
  175.         
  176.         /*
  177.         *    We will remove any surrounding comments (ignoring
  178.         *    text outside the first level of commenting) and
  179.         *    fix any previously replaced comments.
  180.         */
  181.         
  182.         while ( inT < endT && 
  183.                     !(*inT == '/' && *(inT+1) == '*') ) {
  184.                 inT++; 
  185.             }
  186.         if ( inT < endT )
  187.             inT += 2;
  188.         if ( inT < endT && *inT == '\r' )
  189.             inT++;
  190.         beginning = inT - *inH;
  191.         if ( beginning == inSize )
  192.             beginning = 0;
  193.             
  194.         inT = endT-1;
  195.         temp = *inH + beginning;
  196.         while ( inT > temp && 
  197.                     !(*inT == '*' && *(inT+1) == '/') ) {
  198.                 inT--;
  199.             }
  200.         ending = endT - inT;
  201.         if ( ending == inSize )
  202.             ending = 0;
  203.             
  204.         inT = *inH + beginning;
  205.         endT = *inH + inSize - ending;
  206.         
  207.         while ( inT < endT ) {
  208.             if ( *inT == SLASHREPLACEMENT && 
  209.                 ( *(inT+1) == '*' || *(inT-1) == '*') )
  210.                     *inT = '/';
  211.             inT++;
  212.         }
  213.         
  214.         inT = *inH + beginning;
  215.         outT = AddToOutText(outT,inT,inSize - beginning - ending);
  216.     }
  217.  
  218.     return(outT);
  219. }
  220.         
  221. /*----------------------------------------------------------------------------+
  222. |                    Add comments on the left side of text.                    |
  223. |                    Called when the option key is pressed.                    |
  224. +----------------------------------------------------------------------------*/
  225.                     
  226. Ptr SideNote(inH,inSize)
  227. Handle        inH;
  228. long        inSize;
  229. /*
  230. *    returns pointer to text
  231. */
  232. {
  233.     long        y;
  234.     char        *inT, *endT;
  235.     char        *outT;
  236.     char        buf[256];
  237.     char        firstpart[50];
  238.     long        firstlen;
  239.     long        actualcnt;
  240.     long        firstactual;
  241.     
  242.     inT = *inH;
  243.     endT = inT + inSize;
  244.     
  245.     firstlen = 0; firstactual = 0;
  246.     while (  inT < endT ) {
  247.         if ( *inT == '\r' ) {
  248.             /* end of line...start over */
  249.             *inT++;
  250.             firstlen = 0;
  251.             firstactual = 0;
  252.             continue;
  253.         }
  254.         if ( isspace(*inT) ) {
  255.             firstpart[firstlen] = *inT;
  256.             firstlen++;
  257.             inT++;
  258.             if ( *inT == '\t' ) 
  259.                 firstactual = ((firstactual + TABSPACE)/TABSPACE)*TABSPACE;
  260.             else
  261.                 firstactual++;
  262.         } else 
  263.             /* we've run out of white space */
  264.             break;
  265.     }
  266.     inT = *inH;
  267.  
  268.     outT = NewPtr(0L);
  269.     
  270.     /* now we put in the first line */
  271.     y = 0;
  272.     while ( y < firstlen ) {
  273.         buf[y] = firstpart[y];
  274.         y++;
  275.     }
  276.     buf[y++] = '/';
  277.     buf[y++] = '*';
  278.     buf[y++] = '\r';
  279.     
  280.     outT = AddToOutText(outT,buf,y);
  281.     if ( outT == NULL )
  282.         return(NULL);
  283.         
  284.  
  285.     do {
  286.     
  287.         /*
  288.         *    First we need to remove the beginning part of the the line
  289.         *    so everything lines up properly.
  290.         */
  291.         actualcnt = 0;
  292.         while ( actualcnt < firstactual
  293.              && inT < endT && *inT != '\r' ) { 
  294.              if ( *inT == '\t' )
  295.                  actualcnt = ((actualcnt+TABSPACE)/TABSPACE)*TABSPACE;
  296.              else
  297.                  actualcnt++;
  298.              inT++;
  299.          }
  300.     
  301.         
  302.         if ( *inT == '/' && *(inT+1) == '*' ) {
  303.             /* skip this line */
  304.             while ( inT < endT && *inT != '\r' ) { inT++; }
  305.             if ( inT < endT )
  306.                 inT++;
  307.             continue;
  308.         }
  309.         
  310.         if ( (*inT == '*' && *(inT+1) == '/') ||
  311.             (*inT == '/' && *(inT-1) == '*') ) {
  312.             /* skip this line */
  313.             while ( inT < endT && *inT != '\r' ) { inT++; }
  314.             if ( inT < endT )
  315.                 inT++;
  316.             continue;
  317.         }
  318.             
  319.         if ( *inT == SIDECHAR ) {
  320.             inT++;
  321.             if ( *inT == '\t' )
  322.                 inT++;
  323.         } 
  324.  
  325.         y = 0;
  326.         while ( y < firstlen ) {
  327.             buf[y] = firstpart[y];
  328.             y++;
  329.         }
  330.         buf[y++] = SIDECHAR;
  331.         buf[y++] = '\t';
  332.                     
  333.         while ( inT < endT && *inT != '\r' ) {        
  334.             buf[y++] = *inT;
  335.             inT++;            
  336.         }
  337.         
  338.         if ( *inT == '\r' ) {
  339.             buf[y++] = '\r';
  340.             inT++;
  341.         }
  342.         
  343.         outT = AddToOutText(outT,buf,(long)y);
  344.         if ( outT == NULL )
  345.             return(NULL);
  346.                     
  347.     } while ( inT < endT );
  348.     
  349.     /* now put in last line */
  350.     y = 0;
  351.     while ( y < firstlen ) {
  352.         buf[y] = firstpart[y];
  353.         y++;
  354.     }
  355.     buf[y++] = '*';
  356.     buf[y++] = '/';
  357.     buf[y++] = '\r';
  358.     
  359.     outT = AddToOutText(outT,buf,(long)y);
  360.  
  361.     return(outT);
  362. }
  363.  
  364. /*----------------------------------------------------------------------------+
  365. |                Surround the text with a big box like this.                   |
  366. |                Called when no key is presed for KEYDELAY Ticks.              |
  367. +----------------------------------------------------------------------------*/
  368.                 
  369. Ptr    BigBox(inH,inSize)
  370. Handle        inH;
  371. long        inSize;
  372. /*
  373. *    returns pointer to text
  374. */
  375. {
  376.     long        x,y;
  377.     char        *inT, *endT;
  378.     char        *outT;
  379.     char        buf[256];
  380.     Boolean        firstChar;
  381.     short        actualcnt;
  382.  
  383.     inT = *inH;
  384.     endT = inT + inSize;
  385.         
  386.     outT = NewPtr(0L);
  387.  
  388.     /* put in first line */
  389.     y = 0;
  390.     buf[y++] = '/';
  391.     buf[y++] = '*';
  392.     for ( x = 0; x < LINELEN - 2; x++ ) 
  393.         buf[y++] = TOPCHAR;
  394.     buf[y++] = CORNERCHAR;
  395.     buf[y++] = '\r';
  396.     
  397.     outT = AddToOutText(outT,buf,(long)y);
  398.     
  399.     if ( outT == NULL ) 
  400.         return(NULL);
  401.         
  402.     inT = *inH;
  403.     do {
  404.     
  405.         if ( *inT == '/' && *(inT+1) == '*' && *(inT+2) == TOPCHAR ) {
  406.             /* skip this line */
  407.             while ( inT < endT && *inT != '\r' ) { inT++; }
  408.             if ( inT < endT )
  409.                 inT++;
  410.             continue;
  411.         }
  412.         
  413.         if ( *inT == CORNERCHAR && *(inT+1) == BOTCHAR && *(inT+2) == BOTCHAR ) {
  414.             /* skip this line */
  415.             while ( inT < endT && *inT != '\r' ) { inT++; }
  416.             if ( inT < endT )
  417.                 inT++;
  418.             continue;
  419.         }
  420.             
  421.         firstChar = TRUE;
  422.         y = 0;
  423.         actualcnt = 0;
  424.         buf[y++] = LEFTCHAR;
  425.         actualcnt++;
  426.         while ( inT < endT && *inT != '\r' ) {
  427.  
  428.             if ( firstChar ) {
  429.                 firstChar = FALSE;
  430.                 if ( *inT == LEFTCHAR ) {
  431.                     inT++;
  432.                     continue;
  433.                 }
  434.             }
  435.             
  436.             buf[y++] = *inT;
  437.         
  438.             if ( *inT == '\t' ) 
  439.                 /* tab */
  440.                 actualcnt = ((actualcnt+TABSPACE)/TABSPACE)*TABSPACE;
  441.             else 
  442.                 actualcnt++; 
  443.                                                 
  444.             inT++;
  445.             
  446.         }
  447.         
  448.         if ( *inT == '\r' ) {
  449.             if ( *(inT-1) != RIGHTCHAR || y < 2 ) {
  450.                 
  451.                 /* pad with spaces */
  452.                 while ( actualcnt < LINELEN ) {
  453.                     buf[y++] = ' ';
  454.                     actualcnt++;
  455.                 }
  456.                 buf[y++] = RIGHTCHAR;
  457.                 
  458.             }
  459.             buf[y++] = '\r';
  460.             inT++;
  461.         }
  462.         
  463.         outT = AddToOutText(outT,buf,(long)y);
  464.         if ( outT == NULL )
  465.             return(NULL);
  466.                     
  467.     } while ( inT < endT );
  468.  
  469.  
  470.     /* now put bottom line */
  471.     y = 0;
  472.     buf[y++] = CORNERCHAR;
  473.     for ( x = 0; x < LINELEN - 2; x++ ) 
  474.         buf[y++] = BOTCHAR;
  475.     buf[y++] = '*';
  476.     buf[y++] = '/';
  477.     buf[y++] = '\r';
  478.     
  479.     outT = AddToOutText(outT,buf,(long)y);
  480.  
  481.     return(outT);    
  482. }
  483.  
  484.  
  485.  
  486. /*----------------------------------------------------------------------------+
  487. |                    Main function.                                            |
  488. +----------------------------------------------------------------------------*/
  489.                 
  490. main()
  491. {
  492.     Handle        inH;
  493.     long        inSize;
  494.     long        offset;
  495.     Boolean        useTEScrap = FALSE;
  496.     long        time;
  497.     Boolean        opt = FALSE, tab = FALSE, accent = FALSE;
  498.     Ptr            outT;
  499.     
  500.     time = TickCount();
  501.     do {
  502.         opt = CheckKeyCode(option_kc);
  503.         tab = CheckKeyCode(tab_kc);
  504.         accent = CheckKeyCode(accent_kc);
  505.     } while ( TickCount() - time < KEYDELAY && 
  506.         !(opt || tab || accent) );
  507.     
  508.     if ( opt || tab || accent )
  509.         FlushEvents(keyDownMask+keyUpMask+autoKeyMask,0);
  510.  
  511.     if ( TEGetScrapLen() > 0 ) {
  512.         useTEScrap = TRUE;
  513.         ZeroScrap();
  514.         TEToScrap();
  515.     }
  516.     
  517.     inH = NewHandle(0L);
  518.     inSize = GetScrap(inH,'TEXT',&offset);
  519.     
  520.     if ( inSize < 0 ) {
  521.         /* no text there */
  522.         DisposHandle(inH);
  523.         SysBeep(30);
  524.         return;
  525.     }
  526.     
  527.     MoveHHi(inH);
  528.     HLock(inH);
  529.     
  530.     if ( opt )
  531.         outT = SideNote(inH,inSize);
  532.     else if ( tab )
  533.         outT = CommentOut(inH,inSize,TRUE);
  534.     else if ( accent )
  535.         outT = CommentOut(inH,inSize,FALSE);
  536.     else 
  537.         outT = BigBox(inH,inSize);
  538.         
  539.     HUnlock(inH);    
  540.     DisposHandle(inH);
  541.  
  542.     if ( outT == NULL ) {
  543.         SysBeep(30);
  544.         return;
  545.     }
  546.         
  547.     ZeroScrap();
  548.     PutScrap(GetPtrSize(outT),'TEXT',outT);
  549.     
  550.     if ( useTEScrap )
  551.         TEFromScrap();
  552.         
  553.     DisposPtr(outT);
  554.     return;    
  555. }
  556.  
  557.